<?php

namespace JsonLowCode;

use JsonLowCode\Helps\Random;
use JsonLowCode\Support\Fluent;
use JsonLowCode\Traits\BaseEvents;
use JsonLowCode\Traits\BaseProps;
use JsonLowCode\Traits\HasMake;
use JsonLowCode\Traits\HasPageCache;
use JsonLowCode\Traits\HasSchema;
use JsonLowCode\Traits\Props\HasModelValue;


abstract class Schema extends Fluent
{
    /**
     * 组件名称
     * @var string
     */
    protected string $componentName = "";
    /**
     * 组件props属性组
     * @var array
     */
    protected array $props = [];
    /**
     * 父级 Schema
     * @var Schema|null
     */
    protected ?Schema $parent = null;
    /**
     * @var mixed 子级
     */
    protected mixed $children;

    protected PageCache $pageCache;

    protected string|null $cacheKey = null;


    use HasMake, BaseProps, BaseEvents, HasSchema, HasModelValue, HasPageCache;

    public function __construct($attributes = [])
    {
        parent::__construct($attributes);
        $this->pageCache = PageCache::make();
    }

    /**
     * @param string|null $cacheKey
     * @return $this
     */
    public function setCacheKey(string $cacheKey = null):static
    {
        $this->cacheKey = $cacheKey?:Random::alpha(16);
        return $this;
    }

    /**
     * @param string|null $cacheKey
     * @return string|null
     */
    public function getCacheKey(string $cacheKey = null):?string
    {
        return $cacheKey?:$this->cacheKey;
    }


    /**
     * 设置attributes属性值
     * @param string $key
     * @param mixed $value
     * @return $this
     */
    public function setAttribute(string $key,mixed $value): static
    {
        $this->attributes[$key] = $value;
        return $this;
    }

    /**
     * @param string $key
     * @return mixed
     */
    public function getAttribute(string $key): mixed
    {
        return $this->attributes[$key]??null;
    }

    public function jsonSerialize():array
    {
        $this->componentName($this->componentName);
        $this->setAttribute("cacheKey",$this->cacheKey);
        $parent = $this->parent;
        if ($parent){
            $this->parent = null;
            return $parent->children($this)->jsonSerialize();
        }else{
            return parent::jsonSerialize();
        }
    }
}
